package cn.xshi.actuator.util;

import cn.hutool.core.collection.CollectionUtil;
import cn.xshi.actuator.constant.Constant;
import cn.xshi.actuator.param.ActuatorParam;
import cn.xshi.actuator.vo.ActuatorVO;
import cn.xshi.common.cache.redis.RedisUtil;
import cn.xshi.common.constant.BaseConstant;
import cn.xshi.common.util.JsonUtil;
import cn.xshi.common.util.StringUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.*;

/**
 * @Desc WEB应用监控Server监控工具类
 * @Author 邓纯杰
 * @CreateTime 2012-12-12 12:12:12
 */
@Component
@Slf4j
@Data
public class ActuatorUtil {

    @Resource
    RedisUtil redisUtil;

    /**
     * 存储客户端应用信息至redis中
     * @param actuatorVO
     * @return
     */
    public boolean saveActuator(ActuatorVO actuatorVO){
        if(null == actuatorVO){
            log.warn("ActuatorVO对象不存在");
            return false;
        }
        if(StringUtil.isEmpty(actuatorVO.getClientIp())){
            log.warn("客户端ip不存在");
            return false;
        }
        if(StringUtil.isEmpty(actuatorVO.getApplicationName())){
            log.warn("客户端应用名不存在");
            return false;
        }
        if(null == actuatorVO.getPort()){
            log.warn("客户端端口不存在");
            return false;
        }
        actuatorVO.setUploadTime(System.currentTimeMillis());//上报时间
        //redis 存储key
        String key = BaseConstant.ROOT+Constant.ACTUATOR+actuatorVO.getClientIp();
        String text = redisUtil.get(key);
        if(StringUtil.isEmpty(text)){
            List<ActuatorVO> list = new ArrayList<>();
            list.add(actuatorVO);
            boolean res = redisUtil.set(key, JsonUtil.toFastJson(list));
            return res;
        }else{
            boolean exist = false;
            List<ActuatorVO> list = JsonUtil.toFastList(text,ActuatorVO.class);
            if(!CollectionUtil.isEmpty(list)){
                for (ActuatorVO actuator : list){
                    if(actuator.getPort().intValue()==actuatorVO.getPort().intValue() &&
                            actuatorVO.getApplicationName().equals(actuator.getApplicationName())
                            && actuatorVO.getClientIp().equals(actuator.getClientIp())
                            && actuatorVO.getEnv().equals(actuator.getEnv())){
                        exist = true;
                        break;
                    }
                }
                if(!exist){
                    list.add(actuatorVO);
                }
            }else{
                list = new ArrayList<>();
                list.add(actuatorVO);
            }
            return redisUtil.set(key, JsonUtil.toFastJson(list));
        }
    }

    /**
     * 查询所有客户端应用
     * @return
     */
    public Map<String,List<ActuatorVO>> getActuatorList(){
        Map<String,List<ActuatorVO>> map = new HashMap<>();
        Set<String> keys = redisUtil.getKeys(BaseConstant.ROOT+Constant.ACTUATOR + "*");
        for(String key: keys){
            String text = redisUtil.get(key);
            List<ActuatorVO> list = JsonUtil.toFastList(text,ActuatorVO.class);
            map.put(key.replace(BaseConstant.ROOT+Constant.ACTUATOR,""),list);
        }
        return map;
    }

    /**
     * 获取客户端服务基础URI（用于查询客户端所在的服务JVM等一系列信息）
     * @param actuatorParam
     * @return
     */
    public String getClientBaseUri(ActuatorParam actuatorParam){
        if(StringUtil.isEmpty(actuatorParam.getClientIp())){
            log.warn("未能获取到客户端ip");
            return null;
        }
        if(null == actuatorParam.getPort()){
            log.warn("未能获取到客户端服务应用端口");
            return null;
        }
        if(!actuatorParam.isHasPrefixApplicationName()){
            if(null == actuatorParam.getApplicationName()){
                log.warn("未能获取到客户端服务应用名");
                return null;
            }
            return actuatorParam.getClientHttpPrefix()+"://"+actuatorParam.getClientIp()+":"+actuatorParam.getPort();
        }else{
            return actuatorParam.getClientHttpPrefix()+"://"+actuatorParam.getClientIp()+":"+actuatorParam.getPort()+"/"+actuatorParam.getApplicationName();
        }
    }
}
